//-----------------------------------------------------------------------------
//<filedescription file="SmsPageControl.cs" company="Microsoft">
//  <copyright>
//     Copyright (c) 2005-2006 Microsoft Corporation.  All rights reserved.
//  </copyright>
//  <purpose>
//     Page control base class that can be hosted by Property Sheet, Wizard, and Windows Form.
//  </purpose>
//  <notes>
//  </notes>
//</filedescription>
//-----------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;

namespace DevelopStudio.Basic
{
    /// <summary>
    /// Base class for all items that show up in the Summary/Completion pages.
    /// <remarks>
    /// Do not inherit from this class.
    /// Instead inherit from SmsSummaryAction, or SmsSummaryActionGroup.
    /// </remarks>
    /// </summary>
    public class SmsSummaryItem
    {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="id"></param>
        /// <param name="title"></param>
        public SmsSummaryItem(string id, string title)
        {
            Id = id;
            Title = title;
        }

        /// <summary>
        /// Gets the string used to identify the action.
        /// </summary>
        public string Id { get; private set; }

        /// <summary>
        /// Gets or sets a localized string to display as the heading of the group.
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// Find the SmsSummaryItem with the specified identifier.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual SmsSummaryItem FindItem(string id)
        {
            // See if this is the specified item.
            if (this.Id.Equals(id))
            {
                return this;
            }

            return null;
        }
    }

    /// <summary>
    /// Represents a single action to be displayed in the Summary/Completion pages.
    /// </summary>
    public class SmsSummaryAction : SmsSummaryItem
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="title"></param>
        /// <param name="details"></param>
        public SmsSummaryAction(string id, string title, IEnumerable<string> details) :
            this(id, title)
        {
            if (details != null)
            {
                foreach (string var in details)
                {
                    AddDetail(var);
                }
            }
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="title"></param>
        public SmsSummaryAction(string id, string title) :
            base(id, title)
        {
            Status = ActionStatus.NotStarted;
        }

        /// <summary>
        /// Gets a list of localized strings that are to be displayed as the details of the action.
        /// </summary>
        public ICollection<string> Details { get; private set; }

        /// <summary>
        /// Empties the list of details.
        /// </summary>
        public void ClearDetails()
        {
            Details = null;
        }

        /// <summary>
        /// Add a localized string to the list of details for the action.
        /// </summary>
        /// <param name="message"></param>
        public void AddDetail(string message)
        {
            if (Details == null)
            {
                Details = new List<string>();
            }

            Details.Add(message);
        }

        /// <summary>
        /// Possible values for the SmsSummaryAction's Status.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1708:IdentifiersShouldDifferByMoreThanCase")]
        public enum ActionStatus
        {
            /// <summary>
            /// Not started.
            /// </summary>
            NotStarted = 0,

            /// <summary>
            /// Obsolete: Use ActionStatus.NotStarted
            /// </summary>
            [Obsolete("Use ActionStatus.NotStarted", false)]
            NOT_STARTED = 0,

            /// <summary>
            /// Incomplete.
            /// </summary>
            Incomplete = 1,

#pragma warning disable 3005
            /// <summary>
            /// Obsolete: Use ActionStatus.Incomplete
            /// </summary>
            [Obsolete("Use ActionStatus.Incomplete", false)]
            INCOMPLETE = 1,
#pragma warning restore 3005

            /// <summary>
            /// Completed sucessfully.
            /// </summary>
            CompleteWithSuccess = 2,

            /// <summary>
            /// Obsolete: Use ActionStatus.CompleteWithSuccess
            /// </summary>
            [Obsolete("Use ActionStatus.CompleteWithSuccess", false)]
            COMPLETE_WITH_SUCCESS = 2,

            /// <summary>
            /// Completed with warnings.
            /// </summary>
            CompleteWithWarnings = 3,

            /// <summary>
            /// Obsolete: Use ActionStatus.CompleteWithWarnings
            /// </summary>
            [Obsolete("Use ActionStatus.CompleteWithWarnings", false)]
            COMPLETE_WITH_WARNINGS = 3,

            /// <summary>
            /// Completed with errors.
            /// </summary>
            CompleteWithErrors = 4,

            /// <summary>
            /// Obsolete: Use ActionStatus.CompleteWithErrors
            /// </summary>
            [Obsolete("Use ActionStatus.CompleteWithErrors", false)]
            COMPLETE_WITH_ERRORS = 4,
        };

        /// <summary>
        /// Gets or sets the status of the action.
        /// </summary>
        public ActionStatus Status { get; set; }

        /// <summary>
        /// Gets a list of localized strings to be displayed as warnings that the action produced.
        /// </summary>
        public ICollection<string> Warnings { get; private set; }

        /// <summary>
        /// Add a localized string to the list of warnings the action produced.
        /// </summary>
        /// <param name="message"></param>
        public void AddWarning(string message)
        {
            if (Warnings == null)
            {
                Warnings = new List<string>();
            }

            Warnings.Add(message);
        }

        /// <summary>
        /// Gets a list of localized strings that are to be displayed as errors the action produced.
        /// </summary>
        public ICollection<string> Errors { get; private set; }

        /// <summary>
        /// Add a localized string to the list of errors the action produced.
        /// </summary>
        /// <param name="message"></param>
        public void AddError(string message)
        {
            if (Errors == null)
            {
                Errors = new List<string>();
            }

            Errors.Add(message);
        }

        /// <summary>
        /// Gets a list of localized strings that are to be displayed as steps that can be taken by the user.
        /// </summary>
        public ICollection<string> CorrectiveSteps { get; private set; }

        /// <summary>
        /// Add a localized string to the list that is to be displayed as steps that can be taken by the user.
        /// </summary>
        /// <param name="message"></param>
        public void AddCorrectiveStep(string message)
        {
            if (CorrectiveSteps == null)
            {
                CorrectiveSteps = new List<string>();
            }

            CorrectiveSteps.Add(message);
        }
    }

    /// <summary>
    /// Groups several SmsSummaryAction objects under a single heading.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
    public class SmsSummaryActionGroup : SmsSummaryItem, IList<SmsSummaryAction>
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="title"></param>
        public SmsSummaryActionGroup(string id, string title) :
            base(id, title)
        {
        }

        private List<SmsSummaryAction> actions = new List<SmsSummaryAction>();

        #region Methods for "Find"

        private string findItemID;
        private bool FindItemByID(SmsSummaryItem obj)
        {
            if (obj.Id.Equals(findItemID))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private SmsSummaryAction FindAction(string actionId)
        {
            // Find the action in the list of actions.
            findItemID = actionId;
            SmsSummaryAction action = actions.Find(FindItemByID);

            // Make sure we found one.
            if (action == null)
            {
                throw new ArgumentException("Action corresponding to specified actionID not found");
            }

            return action;
        }

        #endregion

        #region Methods for acting on Actions in the group.

        /// <summary>
        /// Empties the list of details.
        /// </summary>
        public void ClearDetails(string actionId)
        {
            FindAction(actionId).ClearDetails();
        }

        /// <summary>
        /// Add a localized string to the list of details for the action with the specified id.
        /// </summary>
        /// <param name="actionId"></param>
        /// <param name="message"></param>
        public void AddDetail(string actionId, string message)
        {
            FindAction(actionId).AddDetail(message);
        }

        /// <summary>
        /// Update the status for the action with the specified id.
        /// </summary>
        /// <param name="actionId"></param>
        /// <param name="status"></param>
        public void UpdateActionStatus(string actionId, SmsSummaryAction.ActionStatus status)
        {
            FindAction(actionId).Status = status;
        }

        /// <summary>
        /// Add a localized string to the list of warnings the action with the specified id produced.
        /// </summary>
        /// <param name="actionId"></param>
        /// <param name="message"></param>
        public void AddWarning(string actionId, string message)
        {
            FindAction(actionId).AddWarning(message);
        }

        /// <summary>
        /// Add a localized string to the list of errors the action with the specified id produced.
        /// </summary>
        /// <param name="actionId"></param>
        /// <param name="message"></param>
        public void AddError(string actionId, string message)
        {
            FindAction(actionId).AddError(message);
        }

        /// <summary>
        /// Add a localized string to the list that is to be displayed as steps that can be taken by the user.
        /// </summary>
        /// <param name="actionId"></param>
        /// <param name="message"></param>
        public void AddCorrectiveStep(string actionId, string message)
        {
            FindAction(actionId).AddCorrectiveStep(message);
        }

        #endregion

        #region SmsSummaryItem Methods

        /// <summary>
        /// Find the SmsSummaryItem with the specified identifier.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public override SmsSummaryItem FindItem(string id)
        {
            try
            {
                return FindAction(id);
            }
            catch (ArgumentException)
            {
                // Not found. See if the base class can find it.
                return base.FindItem(id);
            }
#if (DEBUG)
            // Only include in debug build; we should not ship with a catch all rather use this to
            //  catch exceptions that we don't handle to determine if we should handle them
            catch (System.Exception ex)
            {
                System.Diagnostics.Debug.Assert(false, String.Format(System.Globalization.CultureInfo.CurrentCulture, "Exception not caught: {0}, {1}", ex.GetType().FullName, ex.ToString()));
                throw;
            }
#endif
        }

        #endregion

        #region IList<SmsSummaryAction> Members

        /// <summary>
        /// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"></see>.
        /// </summary>
        /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"></see>.</param>
        /// <returns>
        /// The index of item if found in the list; otherwise, -1.
        /// </returns>
        public int IndexOf(SmsSummaryAction item)
        {
            return actions.IndexOf(item);
        }

        /// <summary>
        /// Inserts an item to the <see cref="T:System.Collections.Generic.IList`1"></see> at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index at which item should be inserted.</param>
        /// <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1"></see>.</param>
        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"></see> is read-only.</exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">index is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"></see>.</exception>
        public void Insert(int index, SmsSummaryAction item)
        {
            actions.Insert(index, item);
        }

        /// <summary>
        /// Removes the <see cref="T:System.Collections.Generic.IList`1"></see> item at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index of the item to remove.</param>
        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"></see> is read-only.</exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">index is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"></see>.</exception>
        public void RemoveAt(int index)
        {
            actions.RemoveAt(index);
        }

        /// <summary>
        /// Gets or sets the <see cref="T:SmsSummaryAction"/> at the specified index.
        /// </summary>
        /// <value></value>
        public SmsSummaryAction this[int index]
        {
            get
            {
                return actions[index];
            }
            set
            {
                actions[index] = value;
            }
        }

        #endregion

        #region ICollection<SmsSummaryAction> Members

        /// <summary>
        /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"></see>.
        /// </summary>
        /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"></see> is read-only.</exception>
        public void Add(SmsSummaryAction item)
        {
            actions.Add(item);
        }

        /// <summary>
        /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"></see>.
        /// </summary>
        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"></see> is read-only. </exception>
        public void Clear()
        {
            actions.Clear();
        }

        /// <summary>
        /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"></see> contains a specific value.
        /// </summary>
        /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
        /// <returns>
        /// <see langword="true"/> if item is found in the <see cref="T:System.Collections.Generic.ICollection`1"></see>; otherwise, <see langword="false"/>.
        /// </returns>
        public bool Contains(SmsSummaryAction item)
        {
            return actions.Contains(item);
        }

        /// <summary>
        /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"></see> to an <see cref="T:System.Array"></see>, starting at a particular <see cref="T:System.Array"></see> index.
        /// </summary>
        /// <param name="array">The one-dimensional <see cref="T:System.Array"></see> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1"></see>. The <see cref="T:System.Array"></see> must have zero-based indexing.</param>
        /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
        /// <exception cref="T:System.ArgumentOutOfRangeException">arrayIndex is less than 0.</exception>
        /// <exception cref="T:System.ArgumentNullException">array is null.</exception>
        /// <exception cref="T:System.ArgumentException">array is multidimensional.-or-arrayIndex is equal to or greater than the length of array.-or-The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1"></see> is greater than the available space from arrayIndex to the end of the destination array.-or-TemplateType T cannot be cast automatically to the type of the destination array.</exception>
        public void CopyTo(SmsSummaryAction[] array, int arrayIndex)
        {
            actions.CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"></see>.
        /// </summary>
        /// <value></value>
        /// <returns>The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"></see>.</returns>
        public int Count
        {
            get { return actions.Count; }
        }

        /// <summary>
        /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"></see> is read-only.
        /// </summary>
        /// <value></value>
        /// <returns><see langword="true"/> if the <see cref="T:System.Collections.Generic.ICollection`1"></see> is read-only; otherwise, <see langword="false"/>.</returns>
        public bool IsReadOnly
        {
            get { return false; }
        }

        /// <summary>
        /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"></see>.
        /// </summary>
        /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
        /// <returns>
        /// <see langword="true"/> if item was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"></see>; otherwise, <see langword="false"/>. This method also returns <see langword="false"/> if item is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"></see>.
        /// </returns>
        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"></see> is read-only.</exception>
        public bool Remove(SmsSummaryAction item)
        {
            return actions.Remove(item);
        }

        #endregion

        #region IEnumerable<SmsSummaryAction> Members

        /// <summary>
        /// Returns an enumerator that iterates through the collection.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
        /// </returns>
        public IEnumerator<SmsSummaryAction> GetEnumerator()
        {
            return actions.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return actions.GetEnumerator();
        }

        #endregion
    }

    #region Delegate Items

    /// <summary>
    /// Values to tell SummaryActionHandler what type of request is desired.
    /// </summary>
    public enum SummaryRequestType
    {
        /// <summary>
        /// Get summary items.
        /// </summary>
        GetSummaryItems,

        /// <summary>
        /// Add group
        /// </summary>
        AddGroup,

        /// <summary>
        /// Add action.
        /// </summary>
        AddAction,

        /// <summary>
        /// Remove item.
        /// </summary>
        RemoveItem,

        /// <summary>
        /// Replace action.
        /// </summary>
        ReplaceAction,

        /// <summary>
        /// Update action status.
        /// </summary>
        UpdateActionStatus,

        /// <summary>
        /// Clear action details.
        /// </summary>
        ClearActionDetails,

        /// <summary>
        /// Add action detail.
        /// </summary>
        AddActionDetail,

        /// <summary>
        /// Add action warning.
        /// </summary>
        AddActionWarning,

        /// <summary>
        /// Add action error.
        /// </summary>
        AddActionError,

        /// <summary>
        /// Add action corrective step.
        /// </summary>
        AddActionCorrectiveStep,

        /// <summary>
        /// Update action.
        /// </summary>
        UpdateAction,

        /// <summary>
        /// Update group.
        /// </summary>
        UpdateGroup,

        /// <summary>
        /// Get the message at the top of the Summary page.
        /// </summary>
        GetSummaryMessage,

        /// <summary>
        /// Set the message at the top of the Summary page.
        /// </summary>
        SetSummaryMessage,

        /// <summary>
        /// Get the message at the bottom of the Summary page.
        /// </summary>
        GetProceedMessage,

        /// <summary>
        /// Set the message at the bottom of the Summary page.
        /// </summary>
        SetProceedMessage,

        /// <summary>
        /// Get the message at the bottom of the Confirmation page.
        /// </summary>
        GetCloseMessage,

        /// <summary>
        /// Set the message at the bottom of the Confirmation page.
        /// </summary>
        SetCloseMessage,
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <param name="id"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    public delegate object SummaryRequestHandler(SummaryRequestType request, string id, params object[] parameters);

    #endregion
}
